//
//  Wallet.swift
//  XHWalletUtils
//
//  Created by xinph on 2020/5/16.
//  Copyright © 2020 xinph. All rights reserved.
//

import Foundation
import WCDBSwift
import SPDatastorage

public protocol WalletType {
    
    /// 子账户
    var accounts: [Account] { get set }
    /// 助记词
    var mnemonic: String? { get set }
    /// keystore文件
    var keystore: Data? { get set }
    /// 网络环境
    var network: NetworkType { get set }
    /// 是否为分层钱包
    var isHDWallet: Bool { get set }
    /// BIP44
    var purpose: UInt64 { get }
    /// 数据库主键 币种类型 BIP44 https://github.com/satoshilabs/slips/blob/master/slip-0044.md
    var coinType: UInt64 { get }
    /// 钱包路径
    var path: String { get set }
    
    /// 加载完成
    func didLoad()
}

public class Wallet: WalletType, Equatable, TableCodable, CZBDbManagerProtocol {
        
    public var accounts: [Account]

    public var mnemonic: String?
    
    public var privateKey: String?
    
    public var publicKey: String?

    public var keystore: Data?

    public var network: NetworkType

    public var isHDWallet: Bool

    public var purpose: UInt64 = 0

    public var coinType: UInt64 = 0
    
    public var path: String = CoinBIP44.defaultBTCPath

    init(_ mnemonic: String? = nil, keystore: Data? = nil, path: String, isHD: Bool, privateKey: String?, publicKey: String?) {
        self.mnemonic = mnemonic
        self.keystore = keystore
        self.path = path
        self.isHDWallet = isHD
        self.privateKey = privateKey
        self.publicKey = publicKey
        
        accounts = []
        network = Config.default.network
    }
    
    /// 返回一个空钱包
    /// - Returns: 钱包对象
    public class func empty() -> WalletType {
        return Wallet(keystore: Data(), path: CoinBIP44.defaultBTCPath, isHD: false, privateKey: nil, publicKey: nil)
    }

    public static func == (lhs: Wallet, rhs: Wallet) -> Bool {
         return lhs.accounts == rhs.accounts &&
             lhs.mnemonic == rhs.mnemonic &&
             lhs.keystore == rhs.keystore &&
             lhs.path == rhs.path &&
             lhs.network == rhs.network &&
             lhs.purpose == rhs.purpose &&
             lhs.coinType == rhs.coinType &&
             lhs.isHDWallet == rhs.isHDWallet
     }
    
    public enum CodingKeys: String, CodingTableKey {
        public typealias Root = Wallet
        public static let objectRelationalMapping = TableBinding(CodingKeys.self)
        case accounts
        case mnemonic
        case keystore
        case path
        case network
        case isHDWallet
        case purpose
        case coinType
        case privateKey
        case publicKey
        
        public static var columnConstraintBindings: [CodingKeys: ColumnConstraintBinding]? {
            return [
                .privateKey: ColumnConstraintBinding(isPrimary: true, isUnique: true),
            ]
        }
    }
    
    public var isAutoIncrement: Bool = false // 用于定义是否使用自增的方式插入
    public var lastInsertedRowID: Int64 = 0 // 用于获取自增插入后的主键值
    
    public func didLoad() {}
}

extension Wallet: Describable {
    public var description: String {
        get {
            var toReturn = ""
            toReturn = toReturn + "Wallet" + "\n"
            toReturn = toReturn + "accounts: \(self.accounts)" + "\n"
            toReturn = toReturn + "mnemonic: " + (self.mnemonic ?? "") + "\n"
            toReturn = toReturn + "keystore: \(keystore)" + "\n"
            toReturn = toReturn + "keystore: \(path)" + "\n"
            toReturn = toReturn + "network \(self.network)" + "\n"
            toReturn = toReturn + "isHDWallet \(self.isHDWallet)" + "\n"
            toReturn = toReturn + "purpose \(purpose)" + "\n"
            toReturn = toReturn + "coinType \(coinType)" + "\n"
            return toReturn
        }
    }
}
